﻿using MathNet.Numerics;
using MathNet.Numerics.LinearAlgebra.Double;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace mathTest
{

    class Film
    {
        private int forwardPointer;
        private int backwardPointer;
        private int counter;
        private Random rand;

        public Film()
        {
            rand = new Random();

            LoopFilm = Enumerable.Range(1, 120).ToArray();
            FoldPointer = 0;
            ForwardPointer = 0;
            BackwardPointer = 118;


            FilmThickness = Enumerable.Range(1, 120).Select(i => rand.NextDouble() + 10).ToArray();
            Equations = new List<Equation>();
        }

        public DenseMatrix AMatrix { get; set; }
        public DenseVector BVector { get; set; }
        public bool Dir { get; set; }
        public int[] LoopFilm { get; set; }
        public double[] FilmThickness { get; set; }
        public double[] SumOfPairs { get; set; }
        public List<Equation> Equations { get; set; }
        public int UpPointer { get; set; }
        public int DownPointer { get; set; }
        public int FoldPointer { get; set; }
        public int ForwardPointer
        {
            get
            {
                return forwardPointer;
            }
            set
            {
                if (value > 118)
                {
                    forwardPointer = 0;
                }
                else if (value < 0)
                {
                    forwardPointer = 118;
                }
                else
                {
                    forwardPointer = value;
                }
            }
        }

        public int BackwardPointer
        {
            get
            {
                return backwardPointer;
            }
            set
            {
                if (value > 118)
                {
                    backwardPointer = 0;
                }
                else if (value < 0)
                {
                    backwardPointer = 118;
                }
                else
                {
                    backwardPointer = value;
                }
            }
        }

        public int Counter { get => counter; set => counter = value; }

        public double[] SolveMatrix()
        {
            var res = AMatrix.QR().Solve(BVector).ToArray();

            foreach (var item in res)
            {
                Console.WriteLine(item);
            }
            return res;
        }

        public void Generate()
        {
            var r = 119;
            var c = 119;
            double[,] A = new double[r, c];
            for (int row = 0; row < r; row++)
            {
                if (row + 1 == r)
                {
                    A[row, 10] = 1;
                }
                else
                {
                    var res = GetNextPairs();
                    A[row, res[0]] = 1;
                    A[row, res[1]] = 1;
                }
            }
            Random random = new Random();
            double[] b = Enumerable.Range(1, r).Select(i =>
            {
                double v = 20 + random.NextDouble();
                return v;
            }).ToArray();

            b[r - 1] = 10.2;

            PrintMatrix(A, b);

            AMatrix = DenseMatrix.OfArray(A);
            BVector = new DenseVector(b);
        }

        public int[] GetNextPairs()
        {
            Counter++;
            int step = Dir ? 1 : -1;
            var res = new int[] { ForwardPointer, BackwardPointer };
            ForwardPointer += step;
            BackwardPointer -= step;
            if (ForwardPointer - BackwardPointer <= 2 || BackwardPointer - ForwardPointer >= 2)
            {
                Transpose();
                Dir = !Dir;
            }
            return res;
        }

        public void Transpose()
        {
            ForwardPointer += 5;
            BackwardPointer += 5;
        }

        public void PrintPoints()
        {
            foreach (var item in LoopFilm)
            {
                Console.WriteLine(item);
            }
        }

        public void PrintMatrix(double[,] A, double[] b)
        {
            for (int row = 0; row < A.GetLength(0); row++)
            {
                for (int column = 0; column < A.GetLength(1); column++)
                {
                    Console.Write($"{A[row, column]} ");
                }

                Console.Write($"  b{row + 1}={b[row]}  ");
                Console.WriteLine();
            }
        }

        public void PrintRawFilmThickness()
        {
            foreach (var item in FilmThickness)
            {
                Console.WriteLine(item);
            }
        }
        
        private void AddEquation()
        {

            Equations.Add(new Equation() { Point1 = UpPointer, Point2 = DownPointer, Sum = FilmThickness[UpPointer] + FilmThickness[DownPointer] });
        }

        public void GetSumOfPairs()
        {

        }
    }
}
